Skip to content

feat: Split core and puppeteer features#171

Open
regseb wants to merge 1 commit intoXetera:masterfrom
regseb:path
Open

feat: Split core and puppeteer features#171
regseb wants to merge 1 commit intoXetera:masterfrom
regseb:path

Conversation

@regseb
Copy link
Copy Markdown
Contributor

@regseb regseb commented Jun 3, 2025

Fix #152

Split features into two files:

  • core for puppeteer independent features : path()
  • spoof (default) for puppeteer related features and also core: createCursor(), path()

@regseb
Copy link
Copy Markdown
Contributor Author

regseb commented Sep 9, 2025

@Niek Now that the refactor has been merged, can you review this pull request?

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a Puppeteer-independent “core” entry point so consumers can use path generation without pulling in puppeteer types, while keeping the existing Puppeteer-focused API as the default export.

Changes:

  • Added src/core.ts containing path() and PathOptions (no Puppeteer imports).
  • Refactored src/spoof.ts to import/re-export path() and PathOptions from core.
  • Added a package subpath export (ghost-cursor/core) via package.json#exports.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/spoof.ts Removes in-file path() implementation and re-exports it from the new core module.
src/math.ts Introduces a Rectangle type used by core to avoid Puppeteer BoundingBox typing.
src/core.ts New Puppeteer-free module containing path generation logic and related types.
package.json Adds exports map for . (spoof) and ./core entry points.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread package.json
Comment on lines +6 to +14
"exports": {
".": {
"types": "./lib/spoof.d.ts",
"default": "./lib/spoof.js"
},
"./core": {
"types": "./lib/core.d.ts",
"default": "./lib/core.js"
},
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR metadata/issue link indicates this should fix TS users who only import path() without having puppeteer installed, but the root export (".") still points to ./lib/spoof.d.ts, which imports puppeteer types. That means import { path } from 'ghost-cursor' will still fail unless consumers switch to ghost-cursor/core. Consider either (a) making the root export point to core and adding an explicit ./spoof subpath for Puppeteer-specific APIs, or (b) updating public docs (README/changelog) to direct non-Puppeteer users to ghost-cursor/core so the linked issue is actually resolved for readers.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hat do you think @regseb?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It depends on the package's main purpose.

  1. Humanize mouse movements in Puppeteer (and secondary generate human-like movement).

    {
      ".": "./lib/spoof.js",
      "./core": "./lib/core.js"
    }
  2. Generate human-like movement (and secondary provide integration for Puppeteer).

    {
      ".": "./lib/core.js",
      "./puppeteer": "./lib/spoof.js"
    }

With the second solution: there is a breaking change, but it’s easier to add a new integration.

Comment thread package.json
Comment on lines +10 to +14
},
"./core": {
"types": "./lib/core.d.ts",
"default": "./lib/core.js"
},
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a package exports map restricts consumers from importing any previously-available deep paths (e.g. ghost-cursor/lib/... or ghost-cursor/mouse-helper) unless they are explicitly listed. If this package has downstream users relying on those deep imports, this becomes a breaking change. Consider explicitly exporting any intended public subpaths (at least ./spoof, ./mouse-helper, etc.) or doing this behind a major version bump.

Suggested change
},
"./core": {
"types": "./lib/core.d.ts",
"default": "./lib/core.js"
},
},
"./spoof": {
"types": "./lib/spoof.d.ts",
"default": "./lib/spoof.js"
},
"./core": {
"types": "./lib/core.d.ts",
"default": "./lib/core.js"
},
"./lib/*": "./lib/*",

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think people imported these directly, since they are not documented. Right, @regseb?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's unlikely that anyone would import a deeply nested file.

  • It's not common in npm to import deeply nested files.
  • The existence of these files isn't documented.
  • I don't see what functionality a user would want to access in these files.

Comment thread src/core.ts
Comment on lines +39 to +66
/** Generates a set of points for mouse movement between two coordinates. */
export function path (
start: Vector,
end: Vector | Rectangle,
/**
* Additional options for generating the path.
* Can also be a number which will set `spreadOverride`.
*/
// TODO: remove number arg in next major version change, fine to just allow `spreadOverride` in object.
options?: number | PathOptions): Vector[] | TimedVector[] {
const optionsResolved: PathOptions = typeof options === 'number'
? { spreadOverride: options }
: { ...options }

const DEFAULT_WIDTH = 100
const MIN_STEPS = 25
const width = 'width' in end && end.width !== 0 ? end.width : DEFAULT_WIDTH
const curve = bezierCurve(start, end, optionsResolved.spreadOverride)
const length = curve.length() * 0.8

const speed = optionsResolved.moveSpeed !== undefined && optionsResolved.moveSpeed > 0
? (25 / optionsResolved.moveSpeed)
: Math.random()
const baseTime = speed * MIN_STEPS
const steps = Math.ceil((Math.log2(fitts(length, width) + 1) + baseTime) * 3)
const re = curve.getLUT(steps)
return clampPositive(re, optionsResolved)
}
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/core.ts introduces a new public entry point (ghost-cursor/core) and moves core path-generation logic there, but the test suite currently only exercises spoof behavior. Add a small unit test that imports from ../core and asserts basic invariants of path() output (e.g., starts/ends near the requested points, returns non-negative coordinates, timestamps strictly increase when useTimestamps is enabled) to prevent regressions and ensure this entry point stays Puppeteer-free.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot create a unit test based on this feedback. make sure to test the most common edge-cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

puppeteer imported but not in dependencies

3 participants